﻿using System;
using System.Collections.Generic;
using System.Text;

namespace HouseOfCards
{
   /// <summary>
   /// Object that represents a playing card
   /// </summary>
	public class Card
	{
		private byte _value;

      /// <summary>
      /// The ordinal value of the card
      /// </summary>
		public byte Value
		{
			get { return _value; }
		}
		private bool _held;

      /// <summary>
      /// True if the card is held
      /// </summary>
		public bool Held
		{
			get { return _held; }
			set { _held = value; }
		}
		private SuitTypes _suit;

      /// <summary>
      /// The suit of card
      /// </summary>
		public SuitTypes Suit
		{
			get { return _suit; }
		}
		private FaceTypes _face;

      /// <summary>
      /// The face type of the card
      /// </summary>
      /// <remarks><see cref="FaceTypes"/></remarks>
		public FaceTypes Face
		{
			get { return _face; }
		}

      /// <summary>
      /// Creates a new card object
      /// </summary>
      /// <param name="Value">the value of the card</param>
		public Card(byte Value)
		{
			_value = Value;
         _face = GetFaceValue();
         _suit = GetSuitValue();
		}

      /// <summary>
      /// Creates a new card object
      /// </summary>
      /// <param name="cardValue">the value of the card</param>
      public Card(CardValues cardValue)
      {
         _value = (byte)cardValue;
         _face = GetFaceValue();
         _suit = GetSuitValue();
      }

      /// <summary>
      /// Returns the face value of a card
      /// </summary>
      /// <returns><see cref="FaceTypes"/></returns>
      private FaceTypes GetFaceValue()
      {
         return (FaceTypes)(CardFaceValue(_value, GetSuitValue()));
      }

      /// <summary>
      /// Method for returning face value based on raw card value.
      /// The formula for card value is (card = suit + face * 4)
      /// </summary>
      /// <param name="CardValue"></param>
      /// <param name="Suit"></param>
      /// <returns></returns>
      private FaceTypes CardFaceValue(byte CardValue, SuitTypes Suit)
      {
         return (FaceTypes)((CardValue - (int)Suit) / 4);
      }

      /// <summary>
      /// Returns the Suit value of a card
      /// </summary>
      /// <returns><see cref="SuitTypes"/></returns>
      /// <tocexclude/>
      private SuitTypes GetSuitValue()
      {
         switch (_value)
         {
            case 0:
            case 4:
            case 8:
            case 12:
            case 16:
            case 20:
            case 24:
            case 28:
            case 32:
            case 36:
            case 40:
            case 44:
            case 48:
               return SuitTypes.Clubs;
            //break;
            case 1:
            case 5:
            case 9:
            case 13:
            case 17:
            case 21:
            case 25:
            case 29:
            case 33:
            case 37:
            case 41:
            case 45:
            case 49:
               return SuitTypes.Diamonds;
            //break;
            case 2:
            case 6:
            case 10:
            case 14:
            case 18:
            case 22:
            case 26:
            case 30:
            case 34:
            case 38:
            case 42:
            case 46:
            case 50:
               return SuitTypes.Hearts;
            //break;
            default:
               return SuitTypes.Spades;
            //break;
         }
      }
	}

   /// <summary>
   /// Types suits
   /// </summary>
   /// <tocexclude/>
   public enum SuitTypes : byte
	{
		/// <summary>
		/// Clubs
		/// </summary>
      Clubs = 0,
      /// <summary>
      /// Diamonds
      /// </summary>
		Diamonds = 1,
      /// <summary>
      /// Hearts
      /// </summary>
		Hearts = 2,
      /// <summary>
      /// Spades
      /// </summary>
		Spades = 3
	}

   /// <summary>
   /// Suit colors
   /// </summary>
   /// <tocexclude/>
   public enum SuitColorTypes : byte
	{
      /// <summary>
      /// Black
      /// </summary>
		Black = 0,
      /// <summary>
      /// Red
      /// </summary>
		Red = 1
	}

   /// <summary>
   /// Face types
   /// </summary>
   /// <tocexclude/>
   public enum FaceTypes : byte
	{
      /// <summary>
      /// Ace
      /// </summary>
		Ace = 0,
      /// <summary>
      /// Two
      /// </summary>
		Two = 1,
      /// <summary>
      /// Three
      /// </summary>
		Three = 2,
      /// <summary>
      /// Four
      /// </summary>
		Four = 3,
      /// <summary>
      /// Five
      /// </summary>
		Five = 4,
      /// <summary>
      /// Six
      /// </summary>
		Six = 5,
      /// <summary>
      /// Seven
      /// </summary>
		Seven = 6,
      /// <summary>
      /// Eight
      /// </summary>
		Eight = 7,
      /// <summary>
      /// Nine
      /// </summary>
		Nine = 8,
      /// <summary>
      /// Ten
      /// </summary>
		Ten = 9,
      /// <summary>
      /// Jack
      /// </summary>
		Jack = 10,
      /// <summary>
      /// Queen
      /// </summary>
		Queen = 11,
      /// <summary>
      /// King
      /// </summary>
		King = 12
	}
}
